#ifndef _GOVT_CHARACTER_H
#define	_GOVT_CHARACTER_H
/*******************************************************************************
 ** Name: character.h                                                         **
 ** Description:                                                              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved 2-clause BSD License                **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  Redistribution and use in source and binary forms, with or without       **
 **  modification, are permitted provided that the following conditions are   **
 **  met:                                                                     **
 **                                                                           **
 **  * Redistributions of source code must retain the above copyright notice, **
 **    this list of conditions and the following disclaimer.                  **
 **  * Redistributions in binary form must reproduce the above copyright      **
 **    notice, this list of conditions and the following disclaimer in the    **
 **    documentation and/or other materials provided with the distribution.   **
 **                                                                           **
 **  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      **
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED **
 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           **
 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT        **
 ** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    **
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  **
 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR    **
 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    **
 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      **
 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        **
 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              **
 **                                                                           **
 ******************************************************************************/
// Modified $Date: 2011-10-22 02:09:07 +0000 (Sat, 22 Oct 2011) $ by $Author: gian.james $
#define _character_h_ID    "$Id: character.hpp 146 2011-10-22 02:09:07Z gian.james $"
//#include <boost/intrusive/list.hpp>
#include <falcon/engine.h>
#include <list>
#include <odb/core.hxx>
#include "object.hpp"
#include "condition.hpp"
//#include "stat.hpp"
#include "agency.hpp"
#include "professions.hpp"
#include "background.hpp"
#include "occupation.hpp"
#include "mission.hpp"
#include "training.hpp"
#include "container.hpp"
#include "visitor.hpp"
#include "common.hpp"

#define MAX_CHAR_LVL        200		//!< Wow, 200? Really?
#define MAX_USERNAME_LEN	128
#define MAX_PASSWD_LEN		12
#define DEFAULT_STAT		8

// Character flags
#define	CHAR_AUTOJOIN_CHAN	0x0001
#define CHAR_OOC			0x0002	// is player in character or ooc?
#define CHAR_SUSPECT		0x0004	// report some activity to controls
#define CHAR_CAN_BUILD		0x0008	// a builder
#define CHAR_PVP			0x0010	// char is set pvp
#define CHAR_ALLOW_TELL		0x0020	// player allows whispers
#define CHAR_ALLOW_COLOR_THEMES 0x0040	// allow setting up color themes
#define CHAR_HANDLER		0x0080
#define CHAR_CONTROL		0x0100		// Control
#define CHAR_DIRECTOR		0x0200		// players who manage gameplay and content
#define CHAR_GOD			0x0400		// one and only
#define CHAR_MISSION_CTRL	0x0800		// Mission Control
#define CHAR_AGENCY_CTRL	0x1000		// Agency Control
#define CHAR_GAME_CTRL		0x2000		// Game Control

enum class GenderType { Male, Female, Andro };
extern const char * GenderStr[];

//! Character location for items (hit location is a different struct)
enum class CharLocs {
    Head, LArm, RArm, LLeg, RLeg, Chest, Back, LFoot, RFoot, Neck,
    Waist, Finger, Legs
};

// Command/Power Hierarchy
enum class power {
    civilian,   //!< rank 0. guest.
    agent,      //!< rank 1. field agent. most players.
    handler,    //!< rank 2. mission generator.
    control,    //!< rank 3. agency executive.
    director,	//!< rank 4. board of directors sets game policies
    admin       //!< OOC game admin
};

//! General schedule ranks
enum class gs
{
    gs1,        gs2,
    gs3,        gs4,
    gs5,        gs6,
    gs7,        gs8,
    gs9,        gs10,
    gs11,       gs12,
    gs13,       gs14,
    gs15,
    //! Senior Executive Service ranks
    ses1,       ses2,
    ses3,       ses4,

    max
};

// TODO - Maybe remove this.
// Deprecated
enum class Allegience {
	none, self, agency, higher, truth, knowledge, justice
};

class Level
{
public:
	static int	XPNeededForLevel(int l) { return (l*l*1000); }
	static int	XPTillNextLevel(int l, int xp) { return (XPNeededForLevel(l) - xp); }
};

//! @class Character
//! All players are characters.
#pragma db object table("characters")
class Character : public WorldObject
{
public:
    Character();
    explicit Character(const std::string n);
    Character(const Character& orig);
    ~Character();

    virtual std::string TypeToStr() { return "Character"; }

    int	&	Level()  { return lvl; }
    int & XP()  { return xp; }
    int & Wealth()  { return wealth; }
    int  & Reputation()  { return rep; }
    bool & FXSensitive() { return fxsensitive; }

    std::string&   FullName()  { return fullname; }
    std::string&    Height()  { return height; }
    std::string&    Weight()  { return weight; }
    std::string&    Eyes()  { return eyes; }
    std::string&    Hair()  { return hair; }
    std::string&    Skin()  { return skin; }
    ushort &	  Age()  { return age; }
    std::string&	  Codename()  { return codename; }
    boost::shared_ptr<Profession> &	Prof()  { return profession; }
    boost::shared_ptr<Agency> &		Faction()  { return agency; }
    agency::deptnum &	Dept()  { return dept; }
    GenderType &	Gender() { return gender; }

    int			IsControl() { return BMCHK(cflags,CHAR_CONTROL); }
    int			IsHandler() { return BMCHK(cflags,CHAR_HANDLER); }
    int			IsBuilder() { return BMCHK(cflags,CHAR_CAN_BUILD); }
    int			IsGod() { return BMCHK(cflags,CHAR_GOD); }
    int			IsDirector() { return BMCHK(cflags,CHAR_DIRECTOR); }

     void			SetLevel(int l) { lvl = l; }
    void			IncrLevel() { ++lvl; }
    int				IncrEncumbrance(int w) {
    		if (encumbranceCurr += w, w < encumbranceMax)
    	 return encumbranceCurr; else { encumbranceCurr -= w; return 0; } }
    Room *			Location() { return loc; }
    int &			Wanted() { return wanted; }
    double &		Consider() { return consider; }
    int &			PKills() { return pkills; }
    int &			Deaths() { return deaths; }
    entity_t &		Location() { return loc; }
    condition &		Condition() { return cond; }

    boost::shared_ptr<Background> & Bkg() { return background; }
    boost::shared_ptr<Occupation> & Job() { return occupation; }

    int				Actionable();
    int				accept(Pattern::Visitor * v);
    //! Recalculates all stats based on worn, wielded, bkg,occ,prof,etc.
    //! This is an expensive operation. Use with caution.
    void			UpdateStats();

    // The new stat management is in support of ODB ORM ~gian
    ushort &	STR() { return str; }
    ushort &	DEX() { return dex; }
    ushort &	CON() { return con; }
    ushort &	INT() { return inte; }
    ushort &	WIS() { return wis; }
    ushort &	CHA() { return cha; }

    ushort &	STRtemp() { return str_temp; }
    ushort &	DEXtemp() { return dex_temp; }
    ushort &	CONtemp() { return con_temp; }
    ushort &	INTtemp() { return inte_temp; }
    ushort &	WIStemp() { return wis_temp; }
    ushort &	CHAtemp() { return cha_temp; }

    short &	STRbonus() { return str_bonus; }
    short &	DEXbonus() { return dex_bonus; }
    short &	CONbonus() { return con_bonus; }
    short &	INTbonus() { return inte_bonus; }
    short &	WISbonus() { return wis_bonus; }
    short &	CHAbonus() { return cha_bonus; }

    ushort &	DEF() { return def; }
    ushort &	AVD() { return avd; }
    ushort &	INIT() { return init; }

    ushort &	DEFtemp() { return def_temp; }
    ushort &	AVDtemp() { return avd_temp; }
    ushort &	INITtemp() { return init_temp; }

    ushort &	Fort() { return fort; }
    ushort &	Will() { return will; }
    ushort &	Reflex() { return reflex; }
    ushort &	Recovery() { return recovery; }

    ushort &	Rank() { return rank; }

    std::string & Title() { return title; }
    void		AddTitle(std::string t) { titles.push_back(t); }

private:
    friend class odb::access;
    std::string    fullname;
    std::string		codename;
    std::string    height;
    std::string    weight;
    std::string    eyes;
    std::string    hair;
    std::string    skin;
    ushort		age;
    GenderType		gender;

    // Change in support of ODB ORM types. ~gian
    ushort		str,dex,con,inte,wis,cha;
    ushort		str_temp,dex_temp,con_temp,inte_temp,wis_temp,cha_temp;
    short		str_bonus,dex_bonus,con_bonus,inte_bonus,wis_bonus,cha_bonus;

    ushort		def,avd,init,speed;
    ushort		def_temp, avd_temp, init_temp,speed_temp;

    ushort		fort,will,reflex,recovery;

//    BaseStat    _base;       //!< str,dex,con,int,wis,cha
//    DerivedStat _derived;    //!< def,speed,init,bab,etc
//    SavingThrow _saves;      //!< fort,reflex,will,recovery

    int  xp;	// int max = 4.2B
    int     rep;
    int  wealth;
    int     lvl;    //!< career level (ie 3)
    bool    fxsensitive; //!< astral-sensitive
    int     wanted;     //!< crimes & other deeds increase your wanted level
    double	consider;	// this is what 'consider' compares.
    int		pkills;		//!< number of player kills
    int		deaths;		//!< number of deaths
#pragma db column("encumbrance_curr")
    ushort	encumbranceCurr;
#pragma db column("encumbrance_pct")
    ushort	encumbrancePct;
#pragma db column("encumbrance_max")
    ushort	encumbranceMax;
    int		favor;		//!< voted-on attribute: are you loved or despised?
    flags16	cflags;		//!< character flags
    entity_t	loc;

    
    // Condition
    condition	cond;
    
    // Background
    boost::shared_ptr<Background>	background;

    // Occupation
    boost::shared_ptr<Occupation>	occupation;

    // Profession
    boost::shared_ptr<Profession>	 profession;

    // Department
    agency::deptnum		dept;

    // Agency
    boost::shared_ptr<Agency> 	agency;
    ushort				rank;

    std::string		title;
    std::list<std::string> titles;


};

//! @class Dossier
//! @brief A character's dossier
//! Top-level class that holds and is responsible for memory of all characters
//! that are online.
class Dossier
{
public:
	Dossier(Character * a) { agent = a; }
	~Dossier() { delete agent; }

	Character * 	Agent() { return agent; }

private:
    Character   *   	agent;
    // TODO These should be id's into DB lists
    std::list<Mission* > currentMissions;	// these are just pointers to standard
    std::list<Mission* > completedMissions;	// missions owned by the world
    std::list<std::string> awards;
    std::list<Training *>	training;		// points to world-owned training objs
    Training *				currentTraining;	// buffs from this training are in play
};

// Falcon scripting support
//! @class FCharacter
//! @brief Falcon scripting support for Character
class FCharacter : public Falcon::CoreObject
{
public:
	FCharacter(const Falcon::CoreClass * generator, const Character * c);
	FCharacter(const Character &);

	const Character & getCharacter() const { return *character; }
	Character *		getCharacter() { return character; }

private:
	Character * character;
};



#endif	/* _GOVT_CHARACTER_H */

